#include "lcd_init.h"
#include "stdio.h"
#include <string.h>
// #include "app.h"

typedef void (*FunType)(void);
//**********************************write function begin********************************************
void wr_cmd_4spi_8bcs(uint8_t par)
{
    // LCD_DCXLow();
    LCD_CSLow();

    LCD_SCLLow();
    LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x80)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x40)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x20)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x10)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x08)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x04)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x02)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x01)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_CSHigh();
    // LCD_DCXHigh();
    // HAL_Delay(5);
}
void wr_dat_4spi_8bcs(uint8_t par)
{
    LCD_CSLow();
    LCD_SCLLow();
    LCD_SDAHigh();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x80)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x40)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x20)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x10)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x08)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x04)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x02)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x01)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_CSHigh();
    LCD_DCXHigh();
    // HAL_Delay(1);
}
void wr_cmd_parall1_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_dat_parall1_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_cmd_parall2_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
void wr_dat_parall2_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
//**********************************read function begin********************************************
void pb_out(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // db 0-7
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                          GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void pb_in(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // db 0-7
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                          GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
uint8_t i801_read_byte(void)
{
    uint8_t v;

    LCD_DCXHigh();
    LCD_RDLow();
    v = GPIOB->IDR;
    LCD_RDHigh();

    return v;
}
void rd_parall1_8(uint8_t c, uint8_t *d, uint32_t l)
{
    uint8_t buf[128];

    wr_cmd_parall1_8(c);
    pb_in();
    for (int i = 0; i < l; i++)
    {
        buf[i] = i801_read_byte();
    }
    LCD_CSHigh();
    pb_out();
    memcpy(d, buf, l);
}

void Write(uint8_t dc, uint8_t par)
{
    LCD_CSLow();

    if (dc == Command)
    {
        LCD_DCXLow();
    }
    else if (dc == Parameter)
    {
        LCD_DCXHigh();
    }

    for (uint8_t i = 0; i < 8; i++)
    {
        LCD_SCLLow();
        if ((par & 0x80) != 0)
        {
            LCD_SDAHigh();
        }
        else
        {
            LCD_SDALow();
        }
        LCD_SCLHigh();
        par = par << 1;
    }
    LCD_CSHigh();
    LCD_SCLHigh();
}

void HW_Reset(void)
{
    LCD_RSTHigh();
    HAL_Delay(120);
    LCD_RSTLow();
    HAL_Delay(120);
    LCD_RSTHigh();
    HAL_Delay(200);
}

void MDELAY(uint32_t ms)
{
    HAL_Delay(ms);
}

void SPI_WriteComm(uint16_t par)
{
    Write(0, par);
}

void SPI_WriteData(uint16_t par)
{
    Write(1, par);
}
/*
void SPI_WriteComm(uint8_t cmd)
{
    LCD_DCXLow();
    LCD_CSLow();
    for (uint8_t i = 0; i < 8; i++)
    {
        LCD_SCLLow();
        if (cmd & 0x80)
        {
            LCD_SDAHigh();
        }
        else
        {
            LCD_SDALow();
        }
        cmd <<= 1;
        LCD_SCLHigh();
    }
    LCD_DCXHigh();
    LCD_CSHigh();
}

void SPI_WriteData(uint8_t dat)
{
    LCD_DCXHigh();
    LCD_CSLow();
    for (uint8_t i = 0; i < 8; i++)
    {
        LCD_SCLLow();
        if (dat & 0x80)
        {
            LCD_SDAHigh();
        }
        else
        {
            LCD_SDALow();
        }
        dat <<= 1;
        LCD_SCLHigh();
    }
    LCD_DCXHigh();
    LCD_CSHigh();
}
*/
void initial(void)
{
    HW_Reset();
    SPI_WriteComm(0xC8);
    SPI_WriteData(0xff);
    SPI_WriteData(0x93);
    SPI_WriteData(0x42);
    SPI_WriteComm(0x3a);
    SPI_WriteData(0x66);
    SPI_WriteComm(0x36);
    SPI_WriteData(0xC8); // A8

    SPI_WriteComm(0xC0); // Power control 1
    SPI_WriteData(0x13);
    SPI_WriteData(0x0e);

    SPI_WriteComm(0xC1); // Power control 2
    SPI_WriteData(0x02);

    // SPI_WriteComm(0xC2); // Power control 3
    // SPI_WriteData(0xb2);

    SPI_WriteComm(0xC5); // VCOM control 1
    SPI_WriteData(0xD9); // 0XD5
    SPI_WriteComm(0xb1);
    SPI_WriteData(0x00);
    SPI_WriteData(0x1B); // 18
    SPI_WriteComm(0xb4);
    SPI_WriteData(0x02);
/*
    SPI_WriteComm(0xb0);
    SPI_WriteData(0xe0); // org:C0 , crack for T7

    SPI_WriteComm(0xF6);
    SPI_WriteData(0x01);
    SPI_WriteData(0x00);
    SPI_WriteData(0x06);

    SPI_WriteComm(0xB5); // Blanking porch control
    SPI_WriteComm(0x06); // 0x02 //VFP
    SPI_WriteComm(0x06); // 0x02 //VBP
    SPI_WriteComm(0x2A); // 0X14//0x0a //HFP
    SPI_WriteComm(0x30); // 0X52//0x14 //HBP

    SPI_WriteComm(0xB6); // Display function control
    SPI_WriteComm(0x0A); // 0x0a//0x02
    SPI_WriteComm(0xA0); // 0x80
    SPI_WriteComm(0x1D); // 0x1d
    SPI_WriteComm(0x04); // 0x04
*/
    SPI_WriteComm(0xE0); // Set Gamma
    SPI_WriteData(0x00);
    SPI_WriteData(0x07); //
    SPI_WriteData(0x0C); //
    SPI_WriteData(0x06); // 0b
    SPI_WriteData(0x15); // 0e
    SPI_WriteData(0x09); //
    SPI_WriteData(0x3A); //
    SPI_WriteData(0x36); // a8
    SPI_WriteData(0x48); // 3b
    SPI_WriteData(0x02); // 0a
    SPI_WriteData(0x0B); // 14
    SPI_WriteData(0x0A); // 06
    SPI_WriteData(0x15); // 10
    SPI_WriteData(0x16); // 09
    SPI_WriteData(0x0F); // 00

    SPI_WriteComm(0XE1); // Set Gamma
    SPI_WriteData(0x00);
    SPI_WriteData(0x25); //
    SPI_WriteData(0x26); //
    SPI_WriteData(0x02); // 04
    SPI_WriteData(0x0E); // 10
    SPI_WriteData(0x03); // 08
    SPI_WriteData(0x3D); //
    SPI_WriteData(0x13); // 47
    SPI_WriteData(0x4E); // 44
    SPI_WriteData(0x03); // 05
    SPI_WriteData(0x0E); // 0b
    SPI_WriteData(0x0B); // 09
    SPI_WriteData(0x34); // 2f
    SPI_WriteData(0x37); // 36
    SPI_WriteData(0x0F); //

    SPI_WriteComm(0x11);
    MDELAY(120);

    SPI_WriteComm(0x29);
    MDELAY(20);
}
